(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  if (!window.Moshu) {
    window.Moshu = new Object();
  }

  window.Moshu.Logger = (function() {

    function Logger() {}

    Logger.redirectOutput = function(domElement) {
      return Moshu.Logger.domElement = domElement;
    };

    Logger.prototype.log = function(msg) {
      if (!Moshu.Logger.domElement) {
        return console.log(msg);
      } else {
        return Moshu.Logger.domElement.innerHTML += "<span style='color:green'>" + msg + "</span><br>";
      }
    };

    Logger.prototype.logError = function(msg) {
      if (!Moshu.Logger.domElement) {
        return console.log(msg);
      } else {
        return Moshu.Logger.domElement.innerHTML += "<span style='color:red'>" + msg + "</span><br>";
      }
    };

    return Logger;

  })();

  window.Moshu.Observable = (function(_super) {

    __extends(Observable, _super);

    function Observable() {
      this.events = [];
    }

    Observable.prototype.bind = function(type, fnc) {
      if (!this.events) {
        this.events = [];
      }
      if (!this.events[type]) {
        this.events[type] = [];
      }
      return this.events[type].push(fnc);
    };

    Observable.prototype.unbind = function(type, fnc) {
      var ev, i, _i, _len, _ref, _results;
      if (this.events) {
        if (this.events[type]) {
          _ref = this.events[type];
          _results = [];
          for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
            ev = _ref[i];
            if (ev === fnc) {
              _results.push(this.events[type].splice(i, 1));
            } else {
              _results.push(void 0);
            }
          }
          return _results;
        }
      }
    };

    Observable.prototype.notify = function(type, args) {
      var fnc, x, _i, _len, _ref;
      if (this.events) {
        x = true;
        if (this.events[type] && this.events[type].length) {
          _ref = this.events[type];
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            fnc = _ref[_i];
            x = x && fnc(args);
          }
        }
        return x;
      }
    };

    return Observable;

  })(Moshu.Logger);

  window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
    return window.setTimeout(callback, 1000 / 60);
  };

  window.startAnimation = function(animationStep) {
    var self;
    self = this;
    return window.requestAnimFrame(animationStep);
  };

  window.Moshu.AnimationManager = {
    stopped: true,
    interval: null,
    observers: [],
    bind: function(obj, fnc) {
      if (typeof fnc === "function") {
        this.observers.push({
          obj: obj,
          fnc: fnc
        });
        return this.start();
      }
    },
    unbind: function(fnc) {
      var i, obs, _i, _len, _ref;
      _ref = this.observers;
      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
        obs = _ref[i];
        if (obs.fnc === fnc) {
          this.observers.splice(i, 1);
        }
      }
      if (!this.observers || this.observers.length === 0) {
        this.stop();
      }
      return this.observers;
    },
    lastTime: null,
    onAnimationFrame: function(time) {
      var dt, i, obs, self, _i, _len, _ref;
      self = window.Moshu.AnimationManager;
      if (!self.stopped) {
        if (self.lastTime && self.observers && self.observers.length > 0) {
          dt = time - self.lastTime;
          _ref = self.observers;
          for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
            obs = _ref[i];
            obs.fnc.call(obs.obj, dt);
          }
        }
        self.lastTime = time;
      }
      if (!self.stopped) {
        return self.interval = window.startAnimation(self.onAnimationFrame);
      }
    },
    start: function() {
      if (this.stopped) {
        this.interval = window.startAnimation(this.onAnimationFrame);
        return this.stopped = false;
      }
    },
    stop: function() {
      this.stopped = true;
      return this.lastTime = null;
    }
  };

  window.Moshu.Test = (function() {

    function Test(name, fnc) {
      this.name = name;
      this.fnc = fnc;
    }

    Test.prototype.test = function() {
      this.failed = false;
      this.fnc();
      return this.failed;
    };

    return Test;

  })();

  window.Moshu.Tests = (function(_super) {

    __extends(Tests, _super);

    function Tests(name) {
      this.name = name;
      this.arr = [];
      this.logger = console.log;
    }

    Tests.prototype.add = function(name, fnc) {
      var test;
      test = new Moshu.Test(name, fnc);
      return this.arr.push(test);
    };

    Tests.prototype.test = function(test, condition) {
      var _i, _len, _ref, _results;
      this.log("Testing...");
      _ref = this.arr;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        this.currentTest = _ref[_i];
        this.log("Testing " + this.currentTest.name);
        if (!this.currentTest.test()) {
          this.log(this.currentTest.name + " passed.");
        } else {
          this.logError(this.currentTest.name + " failed.");
        }
        _results.push(this.log(""));
      }
      return _results;
    };

    Tests.prototype.assert = function(name, condition) {
      if (condition) {
        return this.log(name + " passed.");
      } else {
        this.currentTest.failed = true;
        return this.logError(name + " failed.");
      }
    };

    return Tests;

  })(Moshu.Logger);

}).call(this);
